package top.gytf.unifiedcall.jsr269;

import com.google.auto.service.AutoService;
import top.gytf.unifiedcall.jsr269.code.CodeLocationGenerateProcessor;
import top.gytf.unifiedcall.jsr269.exception.ExceptionGenerateProcessor;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 统一调用注解处理器，负责执行统一调用处理器
 */
@AutoService(Processor.class)
public class Jsr269AnnotationProcessor extends AbstractProcessor {
    private final List<? extends UnifiedCallProcessor> processors;
    private final Set<String> supportedAnnotationTypes;

    public Jsr269AnnotationProcessor() {
        this.processors = Stream.of(
                        new CodeLocationGenerateProcessor(),
                        new ExceptionGenerateProcessor()
                )
                .sorted(Comparator.comparing(UnifiedCallProcessor::order))
                .toList();
        this.supportedAnnotationTypes = processors.stream()
                .map(UnifiedCallProcessor::getSupportedAnnotationTypes)
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return supportedAnnotationTypes;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.RELEASE_17;
    }

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        processors.forEach(processor -> processor.init(processingEnv));
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        processors.forEach(processor -> processor.process(annotations, roundEnv));
        return false;
    }
}
